# set the maze
import pygame
from supp import import_csv_layout, import_cut_graphic
from mazesettings import tile_size, screen_width
from mazetile import StaticTile
from decoration import Sky
from mazeplayer import Player

class Level:
    def __init__(self, level_data, surface, create_q):
        # general setup
        self.display_surface = surface
        self.world_shift = 0 # the scrolling function
        self.current_x = 0
        self.current_y = 0
        
        # connection
        self.create_q = create_q
        '''level_data = maze_level'''

        #player
        player_layout = import_csv_layout(level_data['player'])
        self.player = pygame.sprite.GroupSingle()
        self.goal = pygame.sprite.GroupSingle()
        self.player_setup(player_layout)

        #terrain setup
        terrain_layout = import_csv_layout(level_data['terrain'])
        self.terrain_sprites = self.create_tile_group(terrain_layout,'terrain')

        #question button
        qbutton_layout = import_csv_layout(level_data['qbutton'])
        self.qbutton_sprites = self.create_tile_group(qbutton_layout,'qbutton')

        #decoration
        self.sky = Sky(8)

        self.current_x = 0
        self.current_y = 0

    # set the screen
    def create_tile_group(self,layout,type):
        sprite_group = pygame.sprite.Group()
        
        for row_index, row in enumerate(layout):
            for col_index, val in enumerate(row):
                if val != '-1': # the data are stored in the game-data csv
                    x = col_index * tile_size
                    y = row_index * tile_size
                    
                    # draw different tiles
                    if type == 'terrain':
                        terrain_tile_list = import_cut_graphic('../graphics/terrain.png')
                        tile_surface = terrain_tile_list[int(val)]
                        sprite = StaticTile(tile_size, x, y, tile_surface)
                    
                    if type == 'qbutton': # the ending button
                        qbutton_tile_list = import_cut_graphic('../graphics/qbutton.png')
                        tile_surface = qbutton_tile_list[int(val)]
                        sprite = StaticTile(tile_size, x, y, tile_surface)
                        
                    sprite_group.add(sprite)

        return sprite_group

    # set the player
    def player_setup(self,layout):
        for row_index, row in enumerate(layout):
            for col_index, val in enumerate(row):
                x = col_index * tile_size
                y = row_index * tile_size
                if val == '0':
                   sprite = Player((x,y))
                   self.player.add(sprite)

                if val == '1':
                    p_surface = pygame.image.load('../graphics/character/player2.png').convert_alpha()
                    sprite = StaticTile(tile_size,x,y,p_surface)
                    self.goal.add(sprite)

    # check horizontal collision
    def horizontal_movement_collision(self):
        player = self.player.sprite
        player.rect.x += player.direction.x * player.speed
        collidable_sprites = self.terrain_sprites.sprites() # + ... + ...

        for sprite in collidable_sprites:
            if sprite.rect.colliderect(player.rect):
                # check the moving position
                if player.direction.x < 0:
                    player.rect.left = sprite.rect.right # check the collision of the player's left side and the tile's right side
                    player.on_left = True
                    self.current_x = player.rect.left
                elif player.direction.x > 0:
                    player.rect.right = sprite.rect.left
                    player.on_right = True
                    self.current_x = player.rect.right

        # check whether the player is on the left(right) side of a tile and adjust the colliding animation
        # reduce the possibility of wrong judging
        if player.on_left and (player.rect.left < self.current_x or player.direction.x >= 0):
            player.on_left = False

        if player.on_right and (player.rect.right > self.current_x or player.direction.x <= 0):
            player.on_right = False

    # check vertical collision
    # similar to horizontal collision
    def vertical_movement_collision(self):
        player = self.player.sprite
        player.rect.y += player.direction.y * player.speed
        collidable_sprites = self.terrain_sprites.sprites()

        for sprite in collidable_sprites:
            if sprite.rect.colliderect(player.rect):
                if player.direction.y < 0:
                    player.rect.top = sprite.rect.bottom
                    player.on_ceiling = True
                    self.current_y = player.rect.top
                elif player.direction.y > 0:
                    player.rect.bottom = sprite.rect.top
                    player.on_ground = True
                    self.current_y = player.rect.bottom
        
        # adjusting
        if player.on_ceiling and (player.rect.top < self.current_y or player.direction.y >= 0):
            player.on_ceiling = False

        if player.on_ground and (player.rect.bottom > self.current_y or player.direction.y <= 0):
            player.on_groung = False

    # check the collision with the ending button and call relevant function to change the status
    def check_q(self):
        if pygame.sprite.spritecollide(self.player.sprite, self.goal, False):
            self.create_q(self.display_surface)

    # world shift
    def scroll_x(self):
        player = self.player.sprite
        player_x = player.rect.centerx
        direction_x = player.direction.x

        # check the position of the player to judge the world shift
        # move the screen
        if player_x < screen_width / 4 and direction_x < 0:
            self.world_shift = 2
            player.speed = 0
        elif player_x > screen_width - (screen_width / 4) and direction_x > 0:
            self.world_shift = -2
            player.speed = 0
        # move the player
        else:
            self.world_shift = 0
            player.speed = 2

    def run(self):
        # run the entire game / level
        
        # decoration
        self.sky.draw(self.display_surface)
        # terrain
        self.terrain_sprites.draw(self.display_surface)
        self.terrain_sprites.update(self.world_shift)

        
        # self.qbutton_sprites.draw(self.display_surface)
        self.qbutton_sprites.update(self.world_shift)

        # player
        self.player.update()
        self.goal.update(self.world_shift)
        self.horizontal_movement_collision()
        self.vertical_movement_collision()

        # status
        # qbutton
        self.check_q()

        # draw the screen
        self.scroll_x()
        self.player.draw(self.display_surface)
        self.goal.draw(self.display_surface)